﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading;

namespace OCX02
{
	public class CommonClass
	{
		public static string[] ListTool ={"hand","banshou","qizi","taotong","laxiaoqi","zitongbang","neiliujiaobanshou","chuizi"};
		public static string[] ListChineseTool = { "手", "扳手", "起子", "T型套筒","拉销器", "紫铜棒", "内六角扳手", "锤子"};
        public static int PART_SCORE_PERCENT = 60; //考核模块中，零件的错误所占总成绩的百分比，范围0-100，

        //获取所有按钮
        public static IEnumerable<Button> GetButton(Control.ControlCollection controls)
        {
            return controls.OfType<Panel>().Single(a => a.Name == "panel3").Controls.OfType<FlowLayoutPanel>().Single(b => b.Name == "flowLayoutPanel1").Controls.OfType<Button>();
        }
        //获取所有零件的图片控件
        public static IEnumerable<PictureBox> GetPartPictureBox(Control.ControlCollection controls)
        {
            return controls.OfType<Panel>().Single(a => a.Name == "panel3").Controls.OfType<FlowLayoutPanel>().Single(b => b.Name == "flowLayoutPanel1").Controls.OfType<PictureBox>();
        }
        //获取所有工具的图片控件
        public static IEnumerable<PictureBox> GetToolPictureBox(Control.ControlCollection controls)
        {
            return controls.OfType<Panel>().Single(a => a.Name == "panel3").Controls.OfType<FlowLayoutPanel>().Single(b => b.Name == "flowLayoutPanel2").Controls.OfType<FlowLayoutPanel>().Single(b => b.Name == "flowLayoutPanel3").Controls.OfType<PictureBox>();
        }
        //获取下拉框的控件
        public static ComboBox GetComboBox(Control.ControlCollection controls)
        {
            return controls.OfType<Panel>().Single(a => a.Name == "panel3").Controls.OfType<Panel>().Single(a => a.Name == "panel7").Controls.OfType<ComboBox>().Single(b => b.Name == "comboBox1");
        }
        //获取讲解图片控件
        public static PictureBox GetJiangjie(Control.ControlCollection controls)
        {
            return controls.OfType<Panel>().Single(a => a.Name == "panel3").Controls.OfType<Panel>().Single(a => a.Name == "panel6").Controls.OfType<PictureBox>().Single(b => b.Name == "jiangjie");
        }
        //将List<Part>转为List<String>
        public static List<string> PartToListString(List<Part> PartInfo)
        {
            List<string> ret = new List<string>();
            foreach (var item in PartInfo)
            {
                ret.Add(item.partName);
            }
            return ret;
        }

        //载入Cult3D控件（重载1：分解与结合使用）
		public static List<Part> LoadCult3D(String CoName, Control.ControlCollection controls, AxIECULT3DPLib.AxCult3DP axCult3D,string[] PartList,List<Part> PartInfo, bool ShowPic,int WhichMenu)
		{
            IEnumerable<PictureBox> picBox_part = GetPartPictureBox(controls);
            IEnumerable<PictureBox> picBox_tool = GetToolPictureBox(controls);

            CheckTool(picBox_tool);

            HideAllPartPictureBox(picBox_part);
            HideAllToolPictureBox(picBox_tool);
			
			axCult3D.LoadCult3D(System.IO.Directory.GetCurrentDirectory()+"\\"+CoName+".co");

            DisplayAllToolPictureBox(picBox_tool);
            if (!ShowPic) DisplayAllPartlPictureBox(picBox_part);
            //隐藏或者显示讲解图片
            PictureBox jiangjie = GetJiangjie(controls);
            if (WhichMenu != 0) jiangjie.Visible = false;

            List<string> retPart=null;
            PartInfo = new List<Part>();
            retPart=LoadPartName(System.IO.Directory.GetCurrentDirectory() + "\\" + CoName + ".txt", retPart, PartInfo);

            CheckPart(retPart, picBox_part);

            PartList = retPart.ToArray();
            return PartInfo;
		}
        //载入Cult3D控件（重载2：原理使用）
        public static void LoadCult3D(String CoName, Control.ControlCollection controls, AxIECULT3DPLib.AxCult3DP axCult3D, string[] PartList, string[] PartChineseList,int WhichMenu)
		{
            if (PartList.Count() != PartChineseList.Count())
                MessageBox.Show("零件标识符的个数为"+PartList.Count()+"，但是零件的中文名的个数为"+PartChineseList.Count()+"，两者不匹配！","错误",MessageBoxButtons.OK,MessageBoxIcon.Error);

            axCult3D.LoadCult3D(System.IO.Directory.GetCurrentDirectory() + "\\" + CoName + ".co");

            ComboBox comboBox = GetComboBox(controls);

			foreach (var item in PartChineseList)
			{
				comboBox.Items.Add(item);
			}

            comboBox.DropDownStyle = ComboBoxStyle.DropDownList;
            comboBox.SelectedIndex = 0;
		}
        //载入Cult3D控件（重载3：构造使用）
        public static void LoadCult3D(String CoName, Control.ControlCollection controls, AxIECULT3DPLib.AxCult3DP axCult3D, int WhichMenu)
        {
            DisableAllButton(GetButton(controls));
            axCult3D.LoadCult3D(System.IO.Directory.GetCurrentDirectory() + "\\" + CoName + ".co");
        }	

        public static string unescape(string s)
        {
            string str=s.Substring(8);
            string[] strArr = str.Split(new string[] { "\\u" }, StringSplitOptions.None);
            byte[] byteArr = new byte[strArr.Length * 2];
            for (int i = 0,j=0; i < strArr.Length; i++,j+=2)
            {
                byteArr[j + 1] = Convert.ToByte(strArr[i].Substring(0, 2), 16);
                byteArr[j] = Convert.ToByte(strArr[i].Substring(2, 2), 16);
            }
            str = System.Text.Encoding.Unicode.GetString(byteArr);
            return str;
        }
        //将字符串分割
        public static List<string> SplitFromText(string str, string[] ch)
        {
            List<string> ret = new List<string>();
            str = str.Replace(" ", "");
            str = str.Replace("\r\n", "");

            string[] partE = str.Split(ch,StringSplitOptions.RemoveEmptyEntries);

            foreach (var item in partE)
            {
                if (!item.Contains("|"))
                {
                    ret.Add(item);
                }
            }
            return ret;
        }
		//从配置文件载入文件信息
        public static List<string> LoadPartName(string url, List<string> PartNameList, List<Part> PartInfo)		//读取Txt配置文件里面所有的零件ID
		{
			string filename = url;
			StreamReader reader = null;
			try
			{
				reader = new StreamReader(filename);
				string line;
				string allData="";
				while ((line = reader.ReadLine()) != null)
				{
					allData+=line;
				}
                PartNameList = SplitFromText(allData, new String[]{"#"});
                List<String> PartInfoFormer = SplitFromText(allData,new String[]{"#&","&@"});
                List<String> PartInfoNext = SplitFromText(allData, new String[] { "&@", "@$" });
                List<String> PartInfoTool = SplitFromText(allData, new String[] { "$" });
                foreach (var item in PartNameList)
                {
                    PartInfo.Add(new Part(item));
                    List<string> list;
                    //分割前驱
                    list = SplitFromText(PartInfoFormer[PartInfo.Count - 1], new String[] { "&" });
                    PartInfo.Last().former = list;
                    //分割后继
                    list = SplitFromText(PartInfoNext[PartInfo.Count - 1], new String[] { "@" });
                    PartInfo.Last().next = list;
                    //分割工具
                    PartInfo.Last().toolName = PartInfoTool[PartInfo.Count - 1];
                    //MessageBox.Show(PartInfo.Last().partName + "," + PartInfo.Last().former[0] +","+ PartInfo.Last().next[0] + "," + PartInfo.Last().toolName);
                }
				reader.Close();
			}
			catch (IOException err)
			{
				MessageBox.Show(err.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return null;
			}
            return PartNameList;
		}
        //分解与结合自动播放
        public static bool AutoActivePart(List<Part> PartInfo,string[] PartNameString,int[] TimeListInt,Control.ControlCollection controls,RichTextBox result, AxIECULT3DPLib.AxCult3DP axCult3D,bool ShowPic)
        {
            List<int> TimeList;
            if (TimeListInt != null)
                TimeList = TimeListInt.ToList();
            else
                TimeList = new List<int>();
            List<String> PartName = PartNameString.ToList();
            if (TimeList == null || TimeList.Count==0)
            {
                TimeList = new List<int>();
                for (int i = 0; i < PartInfo.Count; i++)
                {
                    TimeList.Add(5000);
                }
            }
            if(TimeList.Count !=PartInfo.Count)
            {
                MessageBox.Show("每个零件之前的延时个数（"+TimeList.Count+"）和零件个数（"+PartInfo.Count+"）不匹配","错误",MessageBoxButtons.OK,MessageBoxIcon.Error);
                return false;
            }

            foreach (var item in PartInfo)
            {
                bool flag=item.former.Any(a=>a.CompareTo("none")==0);
                if (flag)
                {
                    string str = item.former.Single(a => a.CompareTo("none") == 0);
                    item.former.Remove(str);
                }
                flag = item.next.Any(a => a.CompareTo("none") == 0);
                if (flag)
                {
                    string str = item.next.Single(a => a.CompareTo("none") == 0);
                    item.next.Remove(str);
                }
            }
            Dictionary<string, Part> PartDict = new Dictionary<string, Part>();
            foreach (var item in PartInfo)
            {
                PartDict[item.partName] = item;
            }
            
            List<Part> ActiveList = new List<Part>();
            bool SuccessFlag = true;
            try
            {
                while (PartDict.Count > 0)
                {
                    bool flag = false;
                    foreach (var item in PartName)
                    {
                        string i = item;
                        if (PartDict.ContainsKey(i) && PartDict[i].former.Count == 0)
                        {
                            flag = true;
                            ActiveList.Add(PartDict[i]);
                            foreach (var item2 in PartDict[i].next)
                            {
                                PartDict[item2].former.Remove(i);
                            }
                            PartDict.Remove(i);
                            break;
                        }
                    }
                    if (!flag && PartDict.Count > 0)
                    {
                        SuccessFlag = false;
                        break;
                    }
                }
            }
            catch (Exception e)
            {
                SuccessFlag = false;
                MessageBox.Show(e.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            
            }


            //if (SuccessFlag) MessageBox.Show("成功"); else MessageBox.Show("失败");
            if (!SuccessFlag)
            {
                MessageBox.Show("拓扑排序失败，请检查配置文件是否正确！","错误",MessageBoxButtons.OK,MessageBoxIcon.Error);
                return false;
            }

            for (int i = 0; i < ActiveList.Count; i++)
            {
                Thread.Sleep(TimeList[i]);
                axCult3D.TriggerAction("tool_" + ActiveList[i].toolName, "tool_" + ActiveList[i].toolName);
                
                axCult3D.TriggerAction("active_" + ActiveList[i].partName, "");
                Thread.Sleep(1000);
                ProcessMessage("SUCC: " + ActiveList[i].partName, GetPartPictureBox(controls), result, ShowPic);
            }

            return true;
        }
        //激活零件点击事件，只在结合时有效
		public static void ActivePart(String name, AxIECULT3DPLib.AxCult3DP axCult3D)		
		{
			axCult3D.TriggerAction("zhuangpei",name.Substring(5));
		}
        //激活切换工具事件
		public static void ActiveTool(String name, AxIECULT3DPLib.AxCult3DP axCult3D)		
		{
			axCult3D.TriggerAction(name,name);
		}
        //检查所有的零件PictureBox是否存在
		public static bool CheckPart(List<string> listPart, IEnumerable<PictureBox> picBox)			
		{
			foreach (var i in listPart)
			{
				bool flag=false;
				foreach (var j in picBox)
				{
					if(j.Name.CompareTo("part_"+i)==0) 
					{
						flag=true;
						break;
					}
				}
				if(!flag)
				{
					MessageBox.Show("错误：无法找到零件 part_"+i+" ，请检查！");
					return false;
				}
			}
			return true;
		}
        //检查所有的工具PictureBox是否存在
		public static bool CheckTool(IEnumerable<PictureBox> picBox)			
		{
			foreach (var i in ListTool)
			{
				bool flag = false;
				foreach (var j in picBox)
				{
					if (j.Name.CompareTo("tool_" + i) == 0)
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					MessageBox.Show("错误：无法找到工具 tool_" + i + " ，请检查！");
					return false;
				}
			}
			return true;
		}
		//处理从CO文件接收到的消息
		public static void ProcessMessage(string message,IEnumerable<PictureBox> picBox,RichTextBox result,bool showPic)	//分离时 showPic=true 结合时 showPic=false
		{
            if (message.StartsWith("TIPS"))
            {
                if (Form1.WhichMenu == 1)
                    result.Text = unescape(message);
            }
            else if (message.StartsWith("ERROR")) result.Text = "...";
            else if (message.StartsWith("SUCC"))
            {
                string partName = message.Substring(6);
                if (showPic)
                    DisplayPictureBox("part_" + partName, picBox);
                else
                    HidePictureBox("part_" + partName, picBox);
            }
            else if (message.StartsWith("FINISH"))
            {
                if (Form1.WhichMenu == 1 || Form1.WhichMenu == 0)
                {
                    MessageBox.Show("您已经完成所有的" + (showPic ? "分解" : "结合") + "操作！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    result.Text = "您已经完成所有的" + (showPic ? "分解" : "结合") + "操作！";
                }
                else if(Form1.WhichMenu == 2)
                {
                    int errPart;
                    int errTool;
                    int allNum = 0;

                    foreach (var item in picBox)
                    {
                        if (item.Name.StartsWith("part_")) allNum++;
                    }

                    int[] ts = new int[4];
                    ts[0] = message.IndexOf("errorPartNum");
                    ts[0]+=13;
   
                    ts[2] = message.IndexOf("errorToolNum");
                    ts[1]=ts[2]-1;
                    ts[2]+=13;
                    ts[3]=message.Length;
                    
                    try 
	                {	        
                		errPart=Convert.ToInt32(message.Substring(ts[0],ts[1]-ts[0]));
                        errTool=Convert.ToInt32(message.Substring(ts[2],ts[3]-ts[2]));

                        double score = 1.0 * PART_SCORE_PERCENT* (allNum - errPart)  / allNum + 1.0 * (100 - PART_SCORE_PERCENT) * (allNum - errTool) / allNum;
                        if (score.CompareTo(0.0) < 0) score = 0.0;

                        string ret="错误零件数："+errPart+"\r\n错误工具数："+errTool+"\r\n得分："+String.Format("{0:0}",score);

                        result.Text = ret;
                        MessageBox.Show(ret);
	                }
	                catch (Exception e)
	                {
                        MessageBox.Show(e.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
	                }
                }
            }
            else if (message.StartsWith("INFO"))
            {

            }
            else
            {
                if (Form1.WhichMenu == 1) 
                    result.Text = message;
            } 
		}
        //显示指定图片控件
		public static void DisplayPictureBox(string message, IEnumerable<PictureBox> picBox)		
		{
			foreach (var item in picBox)
			{
				if (item.Name.CompareTo(message) == 0)
				{
					item.Visible = true;
					return;
				}
			}
		}
        //隐藏指定图片控件
		public static void HidePictureBox(string message, IEnumerable<PictureBox> picBox)		
		{
			foreach (var item in picBox)
			{
				if (item.Name.CompareTo(message) == 0)
				{
					item.Visible = false;
					return;
				}
			}
		}
        //隐藏所有的以part_开头和以tool_的PictureBox
		public static void HideAllPartPictureBox(IEnumerable<PictureBox> picBox)		
		{
			foreach (var item in picBox)
			{
				if(item.Name.StartsWith("part_")) item.Visible=false;
			}
		}
        //隐藏所有的以part_开头和以tool_的PictureBox
        public static void HideAllToolPictureBox(IEnumerable<PictureBox> picBox)		
        {
            foreach (var item in picBox)
            {
                if (item.Name.StartsWith("tool_")) item.Visible = false;
            }
        }
        //显示所有的以part_开头的PictureBox
        public static void DisplayAllPartlPictureBox(IEnumerable<PictureBox> picBox)		
		{
			foreach (var item in picBox)
			{
				if(item.Name.StartsWith("part_")) item.Visible=true;
			}
		}
        //显示所有的以tool_开头的PictureBox
        public static void DisplayAllToolPictureBox(IEnumerable<PictureBox> picBox)		
        {
            foreach (var item in picBox)
            {
                if (item.Name.StartsWith("tool_")) item.Visible = true;
            }
        }
        //禁用所有的Button
        public static void DisableAllButton(IEnumerable<Button> buttonSet)
        {
            foreach (var item in buttonSet)
            {
                item.Enabled = false;
            }
        }
        //启用所有的Button
        public static void EnableAllButton(IEnumerable<Button> buttonSet)
        {
            foreach (var item in buttonSet)
            {
                item.Enabled = true;
            }
        }
	}

    public class Part
    {
        public string partName;
        public string partChineseName;
        public List<string> former;
        public List<string> next;
        public string toolName;

        public Part(string name)
        {
            this.partName = name;
            this.partChineseName = name;
            this.former = new List<string>();
            this.next = new List<string>();
            this.toolName = null;
        }
    }
}
